﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IGolovkine.Core.Linq;
using IGolovkine.ShoutCastRipper.Service.Contracts;
using System.ServiceModel;
using System.Threading;

namespace IGolovkine.ShoutCastRipper.Service
{
    [ServiceBehavior(IncludeExceptionDetailInFaults=true, InstanceContextMode=InstanceContextMode.Single)]
    public class AdminService : IAdminServiceContract, IDisposable
    {
        private readonly IStationRipperService _service;
        private readonly StationRipperEventQueue _eventQueue;
        private const int MaxQueueuSize = 1000;

        public AdminService(IStationRipperService ripperService)
        {
            _service = ripperService;
            _service.StationRipperStateChanged += new EventHandler<StationRipperEventArgs>(ServiceStationRipperStateChanged);
            _eventQueue = new StationRipperEventQueue(MaxQueueuSize);
        }

        private void ServiceStationRipperStateChanged(object sender, StationRipperEventArgs e)
        {
            IStationRipper ripper = (IStationRipper) sender;
            StationRipperEventDataContract item = new StationRipperEventDataContract();
            item.Time = DateTime.Now;
            item.SourceName = ripper.Name;
            
            if (e is StationRipperContentTitleChangedEventArgs)
            {
                var evt = (StationRipperContentTitleChangedEventArgs) e;
                item.Description = string.Format("{0}", evt.CurrentValue);
            }
            else if (e is StationRipperStatusChangedEventArgs)
            {
                var evt = (StationRipperStatusChangedEventArgs)e;
                item.Description = string.Format("Status changed from '{0}' to '{1}': {2}", evt.PreviousValue, evt.CurrentValue, evt.Reason);
            }
            else if (e is StationRipperUrlChangedEventArgs)
            {
                var evt = (StationRipperUrlChangedEventArgs)e;
                item.Description = string.Format("Url changed from '{0}' to '{1}'", evt.PreviousValue, evt.CurrentValue);
            }
            _eventQueue.Enqueue(item);
        }

        public IEnumerable<StationRipperEventDataContract> GetEvents(DateTime since)
        {
            return _eventQueue.GetEventsSince(since);
        } 

        public void StopAll()
        {
            _service.Stop();
        }

        public void StartAll()
        {
            _service.Start();
        }

        public void Start(string name)
        {
            this.GetStationRipper(name).Start();
        }

        public void Stop(string name)
        {
            this.GetStationRipper(name).Stop();
        }

        private IStationRipper GetStationRipper(string name)
        {
            return _service.StationRippers.First(r => r.Name == name);
        }

        public IEnumerable<StationRipperStatusDataContract> GetStatuses()
        {
            return _service.StationRippers.ConvertAll(r => this.GetStatus(r.Name));
        }

        public void StopAfterCurrentTitle(string name)
        {
            this.GetStationRipper(name).StopAfterCurrentTitle();
        }

        public void SkipCurrentTitle(string name)
        {
            this.GetStationRipper(name).SkipCurrentTitle(null);
        }

        public void RegisterForCallBacks()
        {
        }

        public IEnumerable<string> GetStationRipperNames()
        {
            return _service.StationRippers.ConvertAll(r => r.Name);
        }

        public void Dispose()
        {
        }

        public StationRipperStatusDataContract GetStatus(string name)
        {
            IStationRipper ripper = this.GetStationRipper(name);
             return new StationRipperStatusDataContract()
            {
                CurrentLength = DateTime.Now - ripper.CurrentContentTitleStartTime,
                Name = ripper.Name,
                Status = ripper.Status.ToString(),
                ContentTitle = ripper.ContentTitle,
                Url = ripper.CurrentUrl
            };
        }
    }
}
